#include "CRFTagger.h"
#include <cmath>
#include <iostream>
namespace MRFPP
{
double CRFTagger::gradient(double* expected)
{
	double s = 0.0;
	int fid = this -> feature_id();
	forwardbackward();
	for(size_t i = 0; i < xsize(); i++)
	{
		std::vector <int> f = feature_index_ -> feature_cache_[fid++];
		for(size_t j = 0; j < ysize(); j++)
		{
			nodePosterior[i][j] = std::exp(forwardMatrix[i][j] - nodePotential[i][j] + backwardMatrix[i][j] - Z_);
			for(size_t k = 0; k < f.size(); k++)
			{
				expected[f[k] + j] += nodePosterior[i][j];
				if( j == 0)
					--expected[f[k] + answer[i]];
			}
		}
		s += nodePotential[i][answer[i]];
		if( i > 0)
		{
			f = feature_index_ -> feature_cache_[fid++];
			for(size_t j = 0; j < ysize(); j++)
			{
				for(size_t k = 0; k < ysize(); k++)
				{
					edgePosterior[k][j] = std::exp(forwardMatrix[i-1][k] + edgePotential[i][k][j] + backwardMatrix[i][j] -Z_);
					expected[f[0] + k*ysize() + j] += edgePosterior[k][j];
				}
			}
			--expected[f[0] + answer[i - 1] * ysize() + answer[i]];
			s += edgePotential[i][answer[i-1]][answer[i]];
		}

	}
	return Z_ - s;
}

void CRFTagger::setTag(std::vector <int>& f)
{
	answer = f;
}
}
